package com.cskaoyan.config.shiroConfig;

import com.cskaoyan.shiro.*;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author tangjian
 * @Date 2021/10/21 16:46
 * @description 多账号体系认证
 */
@Configuration
@EnableConfigurationProperties(ShiroFilterAnon.class)
public class ShiroConfig {

    ShiroFilterAnon shiroFilterAnon;

    public ShiroConfig(ShiroFilterAnon shiroFilterAnon) {
        this.shiroFilterAnon = shiroFilterAnon;
    }

    /**
     * ShiroFilterFactoryBean
     * 设置拦截的url
     * @param defaultWebSecurityManager
     * @return ShiroFilterFactoryBean
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){

        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);

        Map<String, Filter> filters = shiroFilterFactoryBean.getFilters();
        filters.put("authc",new LoginFilter());

        //拦截
        LinkedHashMap<String, String> filterMap = new LinkedHashMap<>();
        //匿名可访问
        List<String> anons = shiroFilterAnon.getAnon();
        for (String anon : anons) {
            filterMap.put(anon, "anon");
        }

        //需要认证
        filterMap.put("/**","authc");

        //设置拦截链
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
        return shiroFilterFactoryBean;
    }

    /**
     * DefaultWebSecurityManager
     * @param customAuthenticator
     * @return DefaultWebSecurityManager
     */
    @Bean
    public DefaultWebSecurityManager securityManager(CustomAuthenticator customAuthenticator,
                                                     CustomRealm adminRealm){
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        defaultWebSecurityManager.setSessionManager(defaultWebSessionManager());
        //可以在这里设置Realm
        defaultWebSecurityManager.setRealm(adminRealm);
        //realms需要设置 认证 和 授权的 分流
        //前台没有授权 遂不放入wxrealm
        //defaultWebSecurityManager.setRealms();
        defaultWebSecurityManager.setAuthenticator(customAuthenticator);


        return defaultWebSecurityManager;
    }


    /**
     * 注册 DefaultWebSessionManager 在这里与shiro统一管理
     * @return
     */
    @Bean
    public DefaultWebSessionManager defaultWebSessionManager(){
        DefaultWebSessionManager defaultWebSessionManager = new CustomSessionManager();
        //cookie的失效时间设置
        //defaultWebSessionManager.setGlobalSessionTimeout();
        return defaultWebSessionManager;
    }

    /**
     * 声明式的注解需要的配置  不需要参数
     * AuthorizationAttributeSourceAdvisor
     * @param defaultWebSecurityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager defaultWebSecurityManager){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(defaultWebSecurityManager);
        return authorizationAttributeSourceAdvisor;
    }

    /**
     * 注册 CustomAuthenticator 在这里与shiro统一管理
     * 作用: 负责 Realms 的分配
     * 参数: 将所有 Realm 传入提供 doMultiRealmAuthentication 方法调用
     * @param adminRealm
     * @param wxUserRealm
     * @return
     */
    @Bean
    public CustomAuthenticator customAuthenticator(CustomRealm adminRealm, WxUserRealm wxUserRealm){
        CustomAuthenticator customAuthenticator = new CustomAuthenticator();

        // 或者在defaultWebSecurityManager设置Realms
        // defaultWebSecurityManager.setRealms();
        ArrayList<Realm> realms = new ArrayList<>();
        realms.add(adminRealm);
        realms.add(wxUserRealm);

        customAuthenticator.setRealms(realms);
        return customAuthenticator;
    }
}
